home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / XLIBP202.ZIP / XBM2.PAS < prev    next >
Pascal/Delphi Source File  |  1994-06-17  |  21KB  |  569 lines

  1. Unit Xbm2;
  2. {#F}
  3. {╔═══════════════════════════════════════════════════════════════════════════╗
  4. ║                                                                           ║
  5. ║                 XLIB v2.0 - Graphics Library for Borland/Turbo Pascal 7.0          ║
  6. ║                                                                           ║
  7. ║               Tristan Tarrant - tristant@cogs.susx.ac.uk                  ║
  8. ║                                                                           ║
  9. ╠═══════════════════════════════════════════════════════════════════════════╣
  10. ║                                                                           ║
  11. ║                                 Credits                                   ║
  12. ║                                                                           ║
  13. ║                             Themie Gouthas                                ║
  14. ║                                                                           ║
  15. ║                            Matthew MacKenzie                              ║
  16. ║                                                                           ║
  17. ║                             Tore Bastiansen                               ║
  18. ║                                                                           ║
  19. ║                                 Andy Tam                                  ║
  20. ║                                                                           ║
  21. ║                               Douglas Webb                                ║
  22. ║                                                                           ║
  23. ║                              John  Schlagel                               ║
  24. ║                                                                           ║
  25. ╠═══════════════════════════════════════════════════════════════════════════╣
  26. ║                                                                           ║
  27. ║           I informally reserve all rights to the code in XLIB             ║
  28. ║       Rights to contributed code is also assumed to be reserved by        ║
  29. ║                          the original authors.                            ║
  30. ║                                                                           ║
  31. ╚═══════════════════════════════════════════════════════════════════════════╝
  32.  
  33. ╔═══════════════════════════════════════════════════════════════════════════╗
  34. ║ XBM2 : EXPORTED PROCEDURES AND FUNCTIONS                                  ║
  35. ╚═══════════════════════════════════════════════════════════════════════════╝
  36.  
  37.     This unit implements a set of functions to operate on bitmaps. XLIB2 uses
  38.     three different kinds of bitmaps :
  39.         Planar Bitmaps (PBMs),
  40.         Video Bitmaps   (VBMs),
  41.         Compiled Bitmaps (CBMs).
  42.  
  43. ╔══════╗
  44. ║ PBMs ║
  45. ╚══════╝
  46.  
  47.     PBMs as used by these functions have the following structure:
  48.  
  49.         byte 0                 The bitmap width in bytes (4 pixel groups) range 1..255
  50.         byte 1                 The bitmap height in rows range 1..255
  51.         byte 2..n1             The plane 0 pixels width*height bytes
  52.         byte n1..n2            The plane 1 pixels width*height bytes
  53.         byte n2..n3            The plane 2 pixels width*height bytes
  54.         byte n3..n4            The plane 3 pixels width*height bytes
  55.  
  56.     These functions provide the fastest possible bitmap blts from system ram
  57.     to video and further, the single bitmap is applicable to all pixel
  58.     alignments. The masked functions do not need separate masks since all non
  59.     zero pixels are considered to be masking pixels, hence if a pixel is 0 the
  60.     corresponding screen destination pixel is left unchanged.
  61.  
  62. ╔══════╗
  63. ║ VBMs ║
  64. ╚══════╝
  65.  
  66. Yet another type of bitmap to complement planar and compiled bitmaps are
  67. Video Bitmaps, VRAM based bitmaps. If a 4 cylinder car is analagous to planar
  68. bitmaps, that is thrifty on memory consumption but low performance and and a
  69. V8 is analagous to Compiled bitmaps, memory guzzlers that really fly, then
  70. VRAM based bitmaps are the 6 cylinder modest performers with acceptable memory
  71. consumption. They are faster, though, only on VLB/PCI video boards.
  72.  
  73. To summarise their selling points, VBM's are moderately fast with fair memory
  74. consumption, and unlike compiled bitmaps, can be clipped. The disadvantages
  75. are that they are limited by the amount of free video ram and have a complex
  76. structure.
  77.  
  78. The VRAM bitmap format is rather complex consisting of components stored in
  79. video ram and components in system ram working together. This complexity
  80. necessitates the existence of a creation function xmakevbm which takes
  81. an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).
  82.  
  83. VBM structure:
  84.  
  85.     word  0   Size          Total size of this VBM structure in bytes
  86.     word  1   ImageWidth    Width in bytes of the image (for all alignments)
  87.     word  2   ImageHeight   Height in scan lines of the image
  88.  
  89.     word  3 Alignment 0  ImagePtr   Offset in VidRAM of this aligned image
  90.     +--word  4              MaskPtr    Offset (within this structure's DS) of
  91.     |   .                               alignment masks
  92.     |   .
  93.     |   .
  94.     |  word  9 Alignment 3  ImagePtr   Offset in VidRAM of this aligned image
  95.     +|--word 10              MaskPtr    Offset (within this structure's DS) of
  96.     ||                                   alignment masks
  97.     ||
  98.     |+->byte 21 (word 11)                -------+-- Image masks for alignment 0
  99.     |   .                                       |
  100.     |   .                                       |
  101.     |   byte  21 + ImageWidth*ImageHeight  -----+
  102.     |
  103.     |   .
  104.     |   . (similaly for alignments 1 - 2 )
  105.     |   .
  106.     |
  107.     +-->byte  21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3
  108.     .                                       |
  109.     .                                       |
  110.     byte  21 + 4*(ImageWidth*ImageHeight) --+
  111.     .
  112.     .
  113.     << Similarly for alignments 2 and 3 >>
  114.     .
  115.     .
  116.     byte 21 + 4*(ImageWidth*ImageHeight)
  117.     -------------
  118.     (And dont forget the corresponding data in video ram)
  119.  
  120. You can see for yourself the complexity of this bitmap format. The image
  121. is stored in video ram in its 4 different alignments with pointers to these
  122. alignments in the VBM. Similarly there are 4 alignments of the corresponding
  123. masks within the VBM itself (towards the end). The mask bytes contain the
  124. plane settings for the corresponding video bytes so that one memory move can
  125. move up to 4 pixels at a time (depending on the mask settings) using the
  126. VGA's latches, theoretically giving you a 4x speed improvement over
  127. conventional blits like the ones implemented in XPBITMAP. In actual fact
  128. its anywhere between 2 and 3 due to incurred overheads.
  129.  
  130. These bitmaps are more difficult to store in files than PBM'S and CBM's but
  131. still posible with a bit of work, so do not dismiss these as too difficult
  132. to use. Consider all the bitmap formats carefully before deciding on which
  133. to use. There may even be situations that a careful application of all three
  134. types would be most effective ie. compiled bitmaps for Background tiles and
  135. the main game character (which never need clipping), VRAM based bitmaps for
  136. the most frequently occuring (oponent, alien etc) characters which get
  137. clipped as they come into and leave your current location and planar bitmaps
  138. for smaller or less frequently encountered characters.}
  139. {$A+,B-,E-,G+,I+,N-,O-,P-,Q-,S-,T-,X+}
  140.  
  141. {$IFDEF DPMI}
  142. {$C FIXED PRELOAD PERMANENT}
  143. {$ENDIF}
  144.  
  145. Interface
  146.  
  147. Uses Xlib2;
  148.  
  149. Procedure XPbmToBm( var source, dest );
  150. { This function converts a bitmap in the planar format to the linear format
  151.     as used by xcompilebitmap.
  152.  
  153.     WARNING: the source and destination bitmaps must be pre - allocated
  154.  
  155.     NOTE: This function can only convert planar bitmaps that are suitable.
  156.     If the source planar bitmap's width (per plane) is >= 256/4
  157.     it cannot be converted. In this situation an error code
  158.     BMWIDTHERROR. On successful conversion 0 is returned.}
  159. Procedure XBmToPbm( var source, dest );
  160. { This function converts a bitmap in the linear format as used by
  161.     xcompilebitmap to the planar formap.
  162.  
  163.     WARNING: the source and destination bitmaps must be pre - allocated
  164.  
  165.     NOTE: This function can only convert linear bitmaps that are suitable.
  166.     If the source linear bitmap's width is not a multiple of 4
  167.     it cannot be converted. In this situation an error code
  168.     BMWIDTHERROR. On successful conversion 0 is returned.}
  169. Procedure XPutMaskedPbm( X, Y,ScrnOffs : word; var Bitmap );
  170. {    Mask write a planar bitmap from system ram to video ram. All zero source
  171.     bitmap bytes indicate destination byte to be left unchanged.
  172.  
  173.     Source Bitmap structure:
  174.  
  175.     Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
  176.     Bitmap data (plane 2)..,Bitmap data (plane 3)..
  177.  
  178.     NOTE: width is in bytes ie lots of 4 pixels
  179.  
  180.     LIMITATIONS: No clipping is supported
  181.                  Only supports bitmaps with widths which are a multiple of
  182.                  4 pixels}
  183. Procedure XPutPbm( X,Y,ScrnOffs:word; var Bitmap );
  184. {  Write a planar bitmap from system ram to video ram.
  185.  
  186.     Source Bitmap structure:
  187.  
  188.     Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
  189.     Bitmap data (plane 2)..,Bitmap data (plane 3)..
  190.  
  191.     NOTE: width is in bytes ie lots of 4 pixels
  192.  
  193.     LIMITATIONS: No clipping is supported
  194.                  Only supports bitmaps with widths which are a multiple of
  195.                  4 pixels}
  196. Procedure XGetPbm( X,Y: word;SrcWidth,SrcHeight:byte;
  197.                                      ScrnOffs:word; var Bitmap );
  198. { Read a planar bitmap to system ram from video ram.
  199.  
  200.     Source Bitmap structure:
  201.  
  202.     Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
  203.     Bitmap data (plane 2)..,Bitmap data (plane 3)..
  204.  
  205.     NOTE: width is in bytes ie lots of 4 pixels
  206.  
  207.     LIMITATIONS: No clipping is supported
  208.                  Only supports bitmaps with widths which are a multiple of
  209.                  4 pixels}
  210. Procedure XFlipMaskedPbm( X,Y,ScrnOffs:word; var Bitmap; Orientation:word );
  211. Procedure XFlipPbm( X,Y,ScrnOffs:word; var Bitmap; Orientation:word );
  212. Procedure XCompilePbm( LogicalWidth : word; var bitmap, output );
  213. Function  XSizeOfCPbm( logicalwidth : word; var bitmap ) : word;
  214. Procedure XCompileBitmap( logicalwidth:word; var bitmap, output );
  215. Function  XSizeOfCBitmap( logicalwidth:word; var bitmap ):word;
  216. Procedure XPutCBitmap( XPos,YPos,PageOffset:word; var Sprite );
  217. Procedure XPutMaskedPBMClipX( X, Y, ScrnOffs:word; var Bitmap );
  218. procedure XPutMaskedPBMClipY( X, Y, ScrnOffs:word; var Bitmap );
  219. Procedure XPutMaskedPBMClipXY( X, Y, ScrnOffs:word; var Bitmap );
  220. Procedure XPutPBMClipX( X, Y, ScrnOffs:word; var Bitmap );
  221. Procedure XPutPBMClipY( X, Y, ScrnOffs : word; var Bitmap );
  222. Procedure XPutPBMClipXY( X, Y, ScrnOffs:word; var Bitmap );
  223. Procedure XStoreVBMImage( VramOffs,Align:word; var LBitmap );
  224. Procedure XPutMaskedVBM( X, Y, ScrnOffs:word; var SrcVBM );
  225. Procedure XPutMaskedVBMClipX( X, Y, ScrnOffs:word; var SrcVBM );
  226. Procedure XPutMaskedVBMClipY( X, Y, ScrnOffs : word; var SrcVBM );
  227. Procedure XPutMaskedVBMClipXY( X, Y, ScrnOffs:word; var SrcVBM );
  228. Function  XMakeVBM( var lbm; var VramStart : word ) : PAlignmentHeader;
  229. Function  Xsizeofcbitmap32(logicalscreenwidth : word; var bitmapin ) : word;
  230. Function  Xcompilebitmap32(logicalscreenwidth : word; var bitmapin, bitmapout ) : word;
  231. Procedure XScale( DestX, DestY, DestWidth, DestHeight, ScrnOffs : word; var Bitmap );
  232. Procedure XMaskedScale( DestX, DestY, DestWidth, DestHeight, ScrnOffs : word; var Bitmap );
  233.  
  234. Implementation
  235. {$IFDEF DPMI}
  236. {$L XBM2.OBP}
  237. {$ELSE}
  238. {$L XBM2.OBJ}
  239. {$ENDIF}
  240. Procedure XPbmToBm( var source, dest ); external;
  241. Procedure XBmToPbm( var source, dest ); external;
  242. Procedure XPutMaskedPbm( X, Y,ScrnOffs : word; var Bitmap ); external;
  243. Procedure XPutPbm( X,Y,ScrnOffs:word; var Bitmap ); external;
  244. Procedure XGetPbm( X,Y: word;SrcWidth,SrcHeight:byte;
  245.                                      ScrnOffs:word; var Bitmap ); external;
  246. Procedure XFlipMaskedPbm( X,Y,ScrnOffs:word; var Bitmap; Orientation:word ); external;
  247. Procedure XFlipPbm( X,Y,ScrnOffs:word; var Bitmap; Orientation:word ); external;
  248. Procedure XCompilePbm( LogicalWidth : word; var bitmap, output ); external;
  249. Function  XSizeOfCPbm( logicalwidth : word; var bitmap ) : word; external;
  250. Procedure XCompileBitmap( logicalwidth:word; var bitmap, output ); external;
  251. Function  XSizeOfCBitmap( logicalwidth:word; var bitmap ):word; external;
  252. Procedure XPutCBitmap( XPos,YPos,PageOffset:word; var Sprite ); external;
  253. Procedure XPutMaskedPBMClipX( X, Y, ScrnOffs:word; var Bitmap ); external;
  254. procedure XPutMaskedPBMClipY( X, Y, ScrnOffs:word; var Bitmap ); external;
  255. Procedure XPutMaskedPBMClipXY( X, Y, ScrnOffs:word; var Bitmap ); external;
  256. Procedure XPutPBMClipX( X, Y, ScrnOffs:word; var Bitmap ); external;
  257. Procedure XPutPBMClipY( X, Y, ScrnOffs : word; var Bitmap ); external;
  258. Procedure XPutPBMClipXY( X, Y, ScrnOffs:word; var Bitmap ); external;
  259. Procedure XStoreVBMImage( VramOffs,Align:word; var LBitmap ); external;
  260. Procedure XPutMaskedVBM( X, Y, ScrnOffs:word; var SrcVBM ); external;
  261. Procedure XPutMaskedVBMClipX( X, Y, ScrnOffs:word; var SrcVBM ); external;
  262. Procedure XPutMaskedVBMClipY( X, Y, ScrnOffs : word; var SrcVBM ); external;
  263. Procedure XPutMaskedVBMClipXY( X, Y, ScrnOffs:word; var SrcVBM ); external;
  264. Procedure XScale( DestX, DestY, DestWidth, DestHeight, ScrnOffs : word; var Bitmap ); external;
  265. Procedure XMaskedScale( DestX, DestY, DestWidth, DestHeight, ScrnOffs : word; var Bitmap ); external;
  266.  
  267. function XMakeVBM( var lbm; var VramStart : word ) : PAlignmentHeader;
  268. var
  269.     LBMHeadr : ^LBMheader;
  270.     VBMHeadr : PAlignmentHeader;
  271.     VBMMaskPtr, p, LBMPixelPtr : ^byte;
  272.     align,BitNum,TempImageWidth, scanline : integer;
  273.     TempWidth,TempHeight,TempSize,MaskSize,VramOffs,MaskSpace : word;
  274.     MaskTemp : byte;
  275. begin
  276.     VramOffs := VramStart;
  277.     LBMHeadr := @lbm;
  278.     TempWidth  := (LBMHeadr^.width+3) div 4+1;
  279.     TempHeight := LBMHeadr^.height;
  280.     TempSize   := TempWidth*TempHeight;
  281.     getmem( VBMHeadr,22+TempSize*4);
  282.     MaskSpace:=22;
  283.     VBMHeadr^.ImageWidth  := TempWidth;
  284.     VBMHeadr^.ImageHeight := TempHeight;
  285.     VBMHeadr^.size := 22+TempSize*4;
  286.     for align := 0 to 3 do
  287.     begin
  288.         VBMHeadr^.alignments[align].ImagePtr := VramOffs;
  289.         XStoreVBMImage(VramOffs,align,lbm);
  290.         MaskSpace := MaskSpace+TempSize;
  291.         VramOffs := VramOffs+TempSize;
  292.     end;
  293.     VBMMaskPtr := ptr(Seg(VBMHeadr^),Ofs(VBMHeadr^)+22);
  294.     for align:=0 to 3 do
  295.     begin
  296.         LBMPixelPtr := ptr(Seg(lbm),Ofs(lbm)+ 2);
  297.         VBMHeadr^.alignments[align].MaskPtr := Ofs(VBMMaskPtr^);
  298.         for scanline := 0 to TempHeight-1 do
  299.         begin
  300.             BitNum := align;
  301.             MaskTemp := 0;
  302.             TempImageWidth := LBMHeadr^.width;
  303.             repeat
  304.                 MaskTemp := MaskTemp or (Ord(LBMPixelPtr^<>0) shl BitNum);
  305.                 LBMPixelPtr := Ptr(Seg(LBMPixelPtr^),Ofs(LBMPixelPtr^)+1);
  306.                 inc(BitNum);
  307.                 if BitNum > 3 then
  308.                 begin
  309.                     VBMMaskPtr^ := MaskTemp;
  310.                     VBMMaskPtr := Ptr(Seg(VBMMaskPtr^),Ofs(VBMMaskPtr^)+1);
  311.                     MaskTemp := 0;
  312.                     BitNum := 0;
  313.                 end;
  314.                 dec(TempImageWidth);
  315.             until TempImageWidth=0;
  316.             if BitNum<>0 then VBMMaskPtr^ := MaskTemp else VBMMaskPtr^ := 0;
  317.             VBMMaskPtr := Ptr(Seg(VBMMaskPtr^),Ofs(VBMMaskPtr^)+1);
  318.         end;
  319.     end;
  320.     VramStart :=VramOffs;
  321.     XMakeVBM := VBMHeadr;
  322. end;
  323.  
  324. Const
  325.     ROLAL = $c0d0;
  326.     SHORTSTORE8  = $44c6;
  327.     STORE8       = $84c6;
  328.     SHORTSTORE16 = $44c7;
  329.     STORE16      = $84c7;
  330.     ADCSIIMMED   = $d683;
  331.     OUTAL        = $ee;
  332.     RETURN       = $cb;
  333.     DWORDPREFIX  = $66;
  334.  
  335. Function xcompilebitmap32(logicalscreenwidth : word; var bitmapin, bitmapout ) : word;
  336. type
  337.     ByteArray = array[0..1] of byte;
  338. var
  339.     height, column, setcolumn, scanx, scany, outputused, width, margin,
  340.     margin2, margin4, pix0, pix1, pix2, pix3, numpix : integer;
  341.     pos : integer;
  342.     bitmap : ByteArray absolute bitmapin;
  343.     output : ByteArray absolute bitmapout;
  344.  
  345. begin
  346.     column := 0;
  347.     setcolumn := 0;
  348.     scanx := 0;
  349.     scany := 0;
  350.     outputused := 0;
  351.     width := bitmap[0];
  352.     height := bitmap[1];
  353.  
  354.     margin := width - 1;
  355.     margin2 := margin - 4;
  356.     margin4 := margin - 12;
  357.  
  358.     while (column < 4) do
  359.     begin
  360.         numpix := 1;
  361.         pix0 := bitmap[scany*width+scanx+2];
  362.         if pix0 <> 0 then
  363.         begin
  364.             if setcolumn <> column then
  365.             begin
  366.                 repeat
  367.                     output[outputused]:=ROLAL and 255;
  368.                     output[outputused+1]:=ROLAL shr 8;
  369.                     inc(outputused,2);
  370.                     output[outputused]:=ADCSIIMMED and 255;
  371.                     output[outputused+1]:=ADCSIIMMED shr 8;
  372.                     inc(outputused,2);
  373.                     output[outputused] := 0;
  374.                     inc(outputused);
  375.                     inc(setcolumn);
  376.                 until setcolumn = column;
  377.                 output[outputused] := OUTAL;
  378.                 inc(outputused);
  379.             end;
  380.             if scanx <= margin2 then
  381.             begin
  382.                 pix1 := bitmap[scany*width+scanx+2 +4];
  383.                 if (pix1 <> 0) and (scanx <= margin4) then
  384.                 begin
  385.                     numpix := 2;
  386.                     pix2 := bitmap[scany*width+scanx+2 +8];
  387.                     pix3 := bitmap[scany*width+scanx+2 +12];
  388.                     if (pix2 <> 0) and (pix3 <> 0) then
  389.                     begin
  390.                         numpix := 4;
  391.                         output[outputused] := DWORDPREFIX;
  392.                         inc(outputused);
  393.                     end;
  394.                 end;
  395.             end;
  396.             pos := (scany * logicalscreenwidth) + (scanx shr 2) - 128;
  397.             if (pos >= -128) and (pos <= 127) then
  398.             begin
  399.                 if numpix = 1 then
  400.                 begin
  401.                     output[outputused]:=SHORTSTORE8 and 255;
  402.                     output[outputused+1]:=SHORTSTORE8 shr 8;
  403.                     inc(outputused,2);
  404.                     output[outputused] := pos;
  405.                     inc(outputused);
  406.                     output[outputused] := pix0;
  407.                     inc(outputused);
  408.                 end else
  409.                 begin
  410.                     output[outputused]:=SHORTSTORE16 and 255;
  411.                     output[outputused+1]:=SHORTSTORE16 shr 8;
  412.                     inc(outputused,2);
  413.                     output[outputused] := pos;
  414.                     inc(outputused);
  415.                     output[outputused] := pix0;
  416.                     inc(outputused);
  417.                     output[outputused] := pix1;
  418.                     inc(outputused);
  419.                     if numpix = 4 then
  420.                     begin
  421.                         output[outputused] := pix2;
  422.                         inc(outputused);
  423.                         output[outputused] := pix3;
  424.                         inc(outputused);
  425.                     end;
  426.                 end;
  427.             end else
  428.             begin
  429.                 if numpix = 1 then
  430.                 begin
  431.                     output[outputused]:=STORE8 and 255;
  432.                     output[outputused+1]:=STORE8 shr 8;
  433.                     inc(outputused,2);
  434.                     output[outputused]:=pos and 255;
  435.                     output[outputused+1]:=pos shr 8;
  436.                     inc(outputused,2);
  437.                     output[outputused] := pix0;
  438.                     inc(outputused);
  439.                 end else
  440.                 begin
  441.                     output[outputused]:=STORE16 and 255;
  442.                     output[outputused+1]:=STORE16 shr 8;
  443.                     inc(outputused,2);
  444.                     output[outputused]:=pos and 255;
  445.                     output[outputused+1]:=pos shr 8;
  446.                     inc(outputused,2);
  447.                     output[outputused] := pix0;
  448.                     inc(outputused);
  449.                     output[outputused] := pix1;
  450.                     inc(outputused);
  451.                     if numpix = 4 then
  452.                     begin
  453.                         output[outputused] := pix2;
  454.                         inc(outputused);
  455.                         output[outputused] := pix3;
  456.                         inc(outputused);
  457.                     end;
  458.                 end;
  459.             end;
  460.         end;
  461.         scanx := scanx + (numpix shl 2);
  462.         if scanx > margin then
  463.         begin
  464.             scanx := column;
  465.             inc(scany);
  466.             if scany = height then
  467.             begin
  468.                 scany := 0;
  469.                 inc(column);
  470.             end;
  471.         end;
  472.     end;
  473.     output[outputused] := return;
  474.     inc(outputused);
  475.     xcompilebitmap32 := outputused;
  476. end;
  477.  
  478. Function xsizeofcbitmap32(logicalscreenwidth : word; var bitmapin ) : word;
  479. type
  480.     ByteArray = array[0..1] of byte;
  481. var
  482.     height, column, setcolumn, scanx, scany, outputused, width, margin,
  483.     margin2, margin4, pix0, pix1, pix2, pix3, numpix : integer;
  484.     pos : integer;
  485.     bitmap : ByteArray absolute bitmapin;
  486.  
  487. begin
  488.     column := 0;
  489.     setcolumn := 0;
  490.     scanx := 0;
  491.     scany := 0;
  492.     outputused := 0;
  493.     width := bitmap[0];
  494.     height := bitmap[1];
  495.  
  496.     margin := width - 1;
  497.     margin2 := margin - 4;
  498.     margin4 := margin - 12;
  499.  
  500.     while (column < 4) do
  501.     begin
  502.         numpix := 1;
  503.         pix0 := bitmap[scany*width+scanx+2];
  504.         if pix0 <> 0 then
  505.         begin
  506.             if setcolumn <> column then
  507.             begin
  508.                 repeat
  509.                     outputused := outputused + 5;
  510.                     inc(setcolumn);
  511.                 until setcolumn = column;
  512.                 inc(outputused);
  513.             end;
  514.             if scanx <= margin2 then
  515.             begin
  516.                 pix1 := bitmap[scany*width+scanx+2 +4];
  517.                 if (pix1 <> 0) and (scanx <= margin4) then
  518.                 begin
  519.                     numpix := 2;
  520.                     pix2 := bitmap[scany*width+scanx+2 +8];
  521.                     pix3 := bitmap[scany*width+scanx+2 +12];
  522.                     if (pix2 <> 0) and (pix3 <> 0) then
  523.                     begin
  524.                         numpix := 4;
  525.                         inc(outputused);
  526.                     end;
  527.                 end;
  528.             end;
  529.             pos := (scany * logicalscreenwidth) + (scanx shr 2) - 128;
  530.             if (pos >= -128) and (pos <= 127) then
  531.             begin
  532.                 if numpix = 1 then
  533.                     outputused := outputused + 4
  534.                 else
  535.                 begin
  536.                     outputused := outputused + 5;
  537.                     if numpix = 4 then
  538.                         outputused := outputused + 2;
  539.                 end;
  540.             end else
  541.             begin
  542.                 if numpix = 1 then
  543.                     outputused := outputused + 5
  544.                 else
  545.                 begin
  546.                     outputused := outputused + 6;
  547.                     if numpix = 4 then
  548.                         outputused := outputused + 2;
  549.                 end;
  550.             end;
  551.         end;
  552.         scanx := scanx + (numpix shl 2);
  553.         if scanx > margin then
  554.         begin
  555.             scanx := column;
  556.             inc(scany);
  557.             if scany = height then
  558.             begin
  559.                 scany := 0;
  560.                 inc(column);
  561.             end;
  562.         end;
  563.     end;
  564.     inc(outputused);
  565.     xsizeofcbitmap32 := outputused;
  566. end;
  567.  
  568. end.
  569.